/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.commands.association;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Property;

import com.cea.papyrus.core.commands.connection.ConnectionReconnectCommand;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * Command that moves an association from one source to another.
 */
public class AssociationReconnectCommand extends ConnectionReconnectCommand {
	
	/**
	 * Creates a new AssociationReconnectCommand.
	 * 
	 * @param newEndpoint the new end point for the graph edge
	 * @param end integer that indicates if it is the source or the target
	 * connection point that is moved. Values can be
	 * <code>ConnectionCommandBase.SOURCE</code> or
	 * <code>ConnectionCommandBase.TARGET</code>.
	 * @param conn the graph edge that represents the association to be reconnected
	 * @param newLocation the new location
	 */
	public AssociationReconnectCommand(GraphEdge conn, GraphElement newEndpoint, Point newLocation, int end) {
		super(conn, newEndpoint, newLocation, end);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.commands.ConnectionReconnectCommand#executeOnBussiness()
	 */
	/**
	 * 
	 */
	@Override
	public void executeOnBussiness() {
		moveAssociation(getNewSourceElement(), getNewTargetElement());
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.commands.ConnectionReconnectCommand#undoOnBussiness()
	 */
	/**
	 * 
	 */
	@Override
	public void undoOnBussiness() {
		moveAssociation(getOldSourceElement(), getOldTargetElement());
	}	
	
	/**
	 * Moves the association to its new source/target elements.
	 * 
	 * @param umlTarget the new  target Classifier for the association
	 * @param umlSource the new source Classifier for the association
	 */
	public void moveAssociation(Element umlSource, Element theumlTarget){
		Element umlTarget;
		if (theumlTarget instanceof ElementImport){
			umlTarget=((ElementImport)theumlTarget).getImportedElement();
		}
		else{
			umlTarget=theumlTarget;
		}
		Association obj=(Association)getEdgeElement();
		((NamedElement)obj).setName("A_" +((NamedElement)umlSource).getName()+ "_"+ ((NamedElement)umlTarget).getName());
		Association asso=(Association)obj;
		//			relation has moved!!
		Property p1= (Property)asso.getMemberEnds().get(0);
		Property p2= (Property)asso.getMemberEnds().get(1);
		org.eclipse.uml2.uml.Classifier movableClassifier;
		Property fixProperty=null;
		Property movableProperty=null;

		if ((p1.getType()==umlTarget)||(p1.getType()==umlSource)){
			movableProperty=p1;
			fixProperty=p2;


		}
		if ((p2.getType()==umlTarget)||(p2.getType()==umlSource)){
			movableProperty=p2;
			fixProperty=p1;
		}
		if (movableProperty.getType()==umlTarget){
			movableClassifier=(org.eclipse.uml2.uml.Classifier)umlSource;}
		else{movableClassifier=(org.eclipse.uml2.uml.Classifier)umlTarget;}

		//move
		if(movableProperty.getOwner()!=asso){//changeParent if not belong to association
			if ( movableProperty.getOwner() instanceof org.eclipse.uml2.uml.Class){
				((org.eclipse.uml2.uml.Class)movableProperty.getOwner()).getOwnedAttributes().remove(p1);
			}
			if ( movableClassifier instanceof org.eclipse.uml2.uml.Class){
				((org.eclipse.uml2.uml.Class)movableClassifier).getOwnedAttributes().add(movableProperty);	
			}
		}
		fixProperty.setType(movableClassifier);
	}

}
